import classNames from "classnames"
import { ChangeEvent, useEffect, useRef, useState } from "react"
import Input, { InputProps } from "../Input/input"
import Icon from "../Icon/icon"
import useDebounce from "../../hooks/useDebounce"
import useClickOutside from "../../hooks/useClickOutside"
import Transition from "../Transition/transition"

export interface LakerProps {
    value:string,
    number?:number
}

export type DataSourceType<T = {}> = T & LakerProps

export interface AutoCompleteProps extends Omit<InputProps,'onSelect' | 'onChange'> {
    fetchSuggestions:(str:string) => DataSourceType[] | Promise<DataSourceType[]>
    onSelect?: (item:DataSourceType) => void,
    // 文本框发生改变的时候触发的事件
    onChange?: (value: string) => void;
    renderOption?: (item:DataSourceType) => React.ReactNode
}

const AutoComplete = ({
    value,
    onSelect,
    onChange,
    renderOption,
    fetchSuggestions,
    ...restProps
}:AutoCompleteProps) => {
    const classes = classNames('leo-auto-complete')
    const [iptValue,setIptValue] = useState(value as string)
    const [suggestions,setSuggestions] = useState<DataSourceType[]>([])
    const [loading,setLoading] = useState(false)
    const debouncedValue = useDebounce(iptValue,500)
    const [showDropdown,setShowDropdown] = useState(false)
    const [highLight,setHighLight] = useState(-1)
    const triggerSearch = useRef(false)
    const componentRef = useRef<HTMLDivElement>(null)
    useClickOutside(componentRef,()=> setSuggestions([]))

    useEffect(() => {
        if(debouncedValue && triggerSearch.current) {
            const results = fetchSuggestions(debouncedValue)
            if(results instanceof Promise) {
                setLoading(true)
                results.then(data => {
                    setSuggestions(data)
                    setLoading(false)
                    if (data.length > 0) {
                        setShowDropdown(true)
                      }
                })
            } else {
                setSuggestions(results)
                if (results.length > 0) {
                    setShowDropdown(true)
                  }
            }
        } else {
            setShowDropdown(false)
        }
    },[debouncedValue])

    const handlerChange = (e:ChangeEvent<HTMLInputElement>) => {
        triggerSearch.current = true
        const value = e.target.value
        setIptValue(value)
    }
    // 选中
    const handlerSelect = (item:DataSourceType) => {
        triggerSearch.current = false
        setIptValue(item.value)
        setShowDropdown(false)
        if(onSelect) {
            onSelect(item)
        }
    }

    // 自定义模板
    const renderTemplate = (item:DataSourceType) => {
        return renderOption ? renderOption(item) : item.value
    }
    // 键盘事件
    const handleKeyDown = (e:React.KeyboardEvent<HTMLInputElement>) => {
        switch (e.key) {
            case 'Enter':
                if(suggestions[highLight]) {
                    handlerSelect(suggestions[highLight])
                }
                break;
            case 'ArrowUp':
                highLight > 0 && setHighLight(highLight - 1)
                break;
            case 'ArrowDown':
                highLight < suggestions.length - 1 && setHighLight(highLight + 1)
                break;
            case 'Escape':
                setShowDropdown(false)
                break;
            default:
                break;
        }
    }

    // 下拉框
    const generateDropdown = () => {
        return (
            <>
            <Transition
                in={showDropdown || loading}
                animation="zoom-in-top"
                timeout={300}
                onExited={() => {setSuggestions([])}}
            >
                <ul className="leo-suggestion-list">
                    { loading &&
                        <div className="suggstions-loading-icon">
                            <Icon icon="spinner" spin/>
                        </div>
                    }
                    {
                        suggestions.map((item,index) => {
                            const clasees = classNames('suggestion-item',{
                                'is-active': index === highLight
                            })
                            return (
                                <li key={index} className={clasees} onClick={() => handlerSelect(item)}>
                                    { renderTemplate(item) }
                                </li>
                            )
                        })
                    }
                </ul>   
            </Transition>
            </>
        )
    }

    return (
        <div className={classes} style={{ width:300 }} ref={componentRef}>
            <Input
                value={iptValue}
                onChange={handlerChange}
                onKeyDown={handleKeyDown}
                {...restProps}
            />
            { generateDropdown() }
        </div>
    )
}

export default AutoComplete